﻿using Microsoft.Extensions.Configuration;
using RuoVea.ExIdGen.Contract;
using RuoVea.ExIdGen.Core;

namespace RuoVea.ExIdGen
{

    /// <summary>
    /// 每增加 1位 WorkerIdBitLength 或 SeqBitLength，生成的ID数字值将会乘以2（基础长度可参考前一节“ID示例”），反之则除以2。
    /// WorkerIdBitLength，机器码位长，决定 WorkerId 的最大值，默认值6，取值范围 [1, 19]，实际上有些语言采用 无符号 ushort (uint16) 类型接收该参数，所以最大值是16，如果是采用 有符号 short (int16)，则最大值为15。
    /// WorkerIdBitLength，机器码位长，决定 WorkerId 的最大值，默认值6，取值范围 [1, 19]，实际上有些语言采用 无符号 ushort (uint16) 类型接收该参数，所以最大值是16，如果是采用 有符号 short (int16)，则最大值为15。
    /// 
    /// 特别提示：如果一台服务器部署多个独立服务，需要为每个服务指定不同的 WorkerId。
    /// 
    /// SeqBitLength，序列数位长，默认值6，取值范围 [3, 21]（建议不小于4），决定每毫秒基础生成的ID个数。规则要求：WorkerIdBitLength + SeqBitLength 不超过 22。
    /// MinSeqNumber，最小序列数，默认值5，取值范围 [5, MaxSeqNumber]，每毫秒的前5个序列数对应编号0-4是保留位，其中1-4是时间回拨相应预留位，0是手工新值预留位。
    /// MaxSeqNumber，最大序列数，设置范围 [MinSeqNumber, 2^SeqBitLength-1]，默认值0，真实最大序列数取最大值（2^SeqBitLength-1），不为0时，取其为真实最大序列数，一般无需设置，除非多机共享WorkerId分段生成ID（此时还要正确设置最小序列数）。
    /// </summary>
    public class ConfigureOption
    {
        internal static IIdGenerator _IdGenInstance = null;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="options"></param>
        public static void Configure(IdGeneratorOptions options)
        {
            _IdGenInstance = new DefaultIdGenerator(options);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="workerId">机器码 必须由外部设定，最大值 2^6-1 </param>
        /// <param name="seqBitLength">机器码 必须由外部设定，最大值 2^6-1 </param>
        public static void Configure(ushort workerId, byte seqBitLength)
        {
            _IdGenInstance = new DefaultIdGenerator(new IdGeneratorOptions() { WorkerId = workerId, SeqBitLength = seqBitLength });
        }
        /// <summary>
        /// 每增加 1位 WorkerIdBitLength 或 SeqBitLength，生成的ID数字值将会乘以2（基础长度可参考前一节“ID示例”），反之则除以2。
        /// WorkerIdBitLength，机器码位长，决定 WorkerId 的最大值，默认值6，取值范围 [1, 19]，实际上有些语言采用 无符号 ushort (uint16) 类型接收该参数，所以最大值是16，如果是采用 有符号 short (int16)，则最大值为15。
        /// WorkerIdBitLength，机器码位长，决定 WorkerId 的最大值，默认值6，取值范围 [1, 19]，实际上有些语言采用 无符号 ushort (uint16) 类型接收该参数，所以最大值是16，如果是采用 有符号 short (int16)，则最大值为15。
        /// 
        /// 特别提示：如果一台服务器部署多个独立服务，需要为每个服务指定不同的 WorkerId。
        /// 
        /// SeqBitLength，序列数位长，默认值6，取值范围 [3, 21]（建议不小于4），决定每毫秒基础生成的ID个数。规则要求：WorkerIdBitLength + SeqBitLength 不超过 22。
        /// MinSeqNumber，最小序列数，默认值5，取值范围 [5, MaxSeqNumber]，每毫秒的前5个序列数对应编号0-4是保留位，其中1-4是时间回拨相应预留位，0是手工新值预留位。
        /// MaxSeqNumber，最大序列数，设置范围 [MinSeqNumber, 2^SeqBitLength-1]，默认值0，真实最大序列数取最大值（2^SeqBitLength-1），不为0时，取其为真实最大序列数，一般无需设置，除非多机共享WorkerId分段生成ID（此时还要正确设置最小序列数）。
        /// </summary>
        /// <param name="configuration"></param>
        public static void Configure(IConfiguration configuration)
        {
            var generator = configuration.GetSection("IdGenerator");
            ushort workerId = 0;
            bool hasGet = ushort.TryParse(generator.GetSection("WorkerId").Value, out workerId);
            byte seqBitLength = 6;
            bool hasSeq = byte.TryParse(generator.GetSection("SeqBitLength").Value, out seqBitLength);
            if (!hasGet) { workerId = 0; }
            if (!hasSeq) { workerId = 6; }
            _IdGenInstance = new DefaultIdGenerator(new IdGeneratorOptions() { WorkerId = workerId, SeqBitLength = seqBitLength });
        }
    }
}